package services

import (
	"encoding/json"
	"fmt"
	cms20190101 "github.com/alibabacloud-go/cms-20190101/v8/client"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	"go.uber.org/zap"
	"purchase-mall/dao/pg"
	"purchase-mall/models"
	"strconv"
	"time"
)

func LogsMetric(ali *models.AliParam, metric string, maxValue string) (err error, aliyun *models.Aliyun) {

	var dimensions []map[string]string
	err = json.Unmarshal([]byte(ali.Dimensions), &dimensions)
	if err != nil {
		fmt.Printf("error is %v\n", err)
		return
	}
	instanceId := dimensions[0]["instanceId"]
	host := dimensions[0]["host"]

	//fmt.Sprintf("dimensions: %v", dimensions)
	// 入库前参数
	period, _ := strconv.Atoi(ali.Period)

	aliyun = &models.Aliyun{
		PeakValue:  392523653,
		PeakTime:   time.Now().Format("2006-01-02 15:04:05"),
		Period:     period,
		TypeName:   ali.Namespace,
		MetricName: metric,
		MaxValue:   95.99,
		CreatedAt:  time.Now().Format("2006-01-02 15:04:05"),
		StatDate:   time.Now().Format("2006-01-02"),
		Instance:   instanceId,
		Host:       host,
	}
	// 入库 pg
	if err = pg.InsertData(aliyun); err != nil {
		zap.L().Error("Kafka.InsertData failed", zap.Error(err))
		return
	}

	return
}

func AliInstance(ali *models.AliParam, metricName string) (_err error, response *cms20190101.DescribeMetricListResponse) {
	client, _err := CreateClient(tea.String("LTAI5tJbjwHniMeGGvL1bPTf"), tea.String("xf0A7cgFxdPiELy0YDbMML6UXBPYE8"))
	if _err != nil {
		return _err, nil
	}

	describeMetricListRequest := &cms20190101.DescribeMetricListRequest{
		//Namespace:  tea.String("acs_kafka"),
		//MetricName: tea.String("instance_disk_capacity"),
		//Period:     tea.String("60"),
		//StartTime:  tea.String("2022-10-27 00:00:00"),
		//EndTime:    tea.String("2022-10-28 00:00:00"),
		//Dimensions: tea.String("[{\"instanceId\": \"alikafka_post-cn-7pp2tik4j014\"}]"),
		Namespace:  tea.String(ali.Namespace),
		MetricName: tea.String(metricName),
		Period:     tea.String(ali.Period),
		StartTime:  tea.String(ali.StartTime),
		EndTime:    tea.String(ali.EndTime),
		Dimensions: tea.String(ali.Dimensions),
	}
	runtime := &util.RuntimeOptions{}

	tryErr := func() (_e error) {
		defer func() {
			if r := tea.Recover(recover()); r != nil {
				_e = r
			}
		}()
		// 复制代码运行请自行打印 API 的返回值
		response, _err = client.DescribeMetricListWithOptions(describeMetricListRequest, runtime)
		if _err != nil {

			return _err
		}
		return nil
	}()
	//fmt.Printf("aliyun response.Body is response %v", response)
	if tryErr != nil {
		var error = &tea.SDKError{}
		if _t, ok := tryErr.(*tea.SDKError); ok {
			error = _t
		} else {
			error.Message = tea.String(tryErr.Error())
		}
		// 如有需要，请打印 error
		_, _err = util.AssertAsString(error.Message)
		if _err != nil {
			return _err, nil
		}

		return error, nil
	}

	//处理需要数据
	//var res AliRespJson
	//err = json.Unmarshal(response, &res)
	//if err != nil {
	//	return
	//}
	if *response.StatusCode != 200 {
		return
	}
	//比较重要 print
	//fmt.Printf("aliyun response is %v", response)
	return _err, response
}

func AliMetric(ali *models.AliParam, metric string, maxValue string) (err error, aliyun *models.Aliyun) {
	//获取阿里原始数据
	err, response := AliInstance(ali, metric)
	if err != nil {
		zap.L().Error("get ali kafka failed", zap.Error(err))
		return
	}
	//格式化需要返回结果
	res, err := FormatRes(response, maxValue)
	if err != nil {
		zap.L().Error("FormatRes failed", zap.Error(err))
		return
	}

	var dimensions []map[string]string
	err = json.Unmarshal([]byte(ali.Dimensions), &dimensions)
	if err != nil {
		fmt.Printf("error is %v\n", err)
		return
	}
	instanceId := dimensions[0]["instanceId"]
	host := dimensions[0]["host"]

	// 入库前参数
	period, _ := strconv.Atoi(ali.Period)

	//对lindrom 磁盘总量特殊处理时间
	if metric == "storage_total_bytes" {
		//res.MaxTime = time.Now().Unix()
		ts := time.Now().AddDate(0, 0, -1)
		timeYesterday := time.Date(ts.Year(), ts.Month(), ts.Day(), 23, 59, 59, 0, ts.Location()).Unix()
		res.MaxTime = timeYesterday
	}

	aliyun = &models.Aliyun{
		PeakValue:  res.MaxNum,
		PeakTime:   time.Unix(res.MaxTime, 0).Format("2006-01-02 15:04:05"),
		Period:     period,
		TypeName:   ali.Namespace,
		MetricName: metric,
		MaxValue:   95.99,
		CreatedAt:  time.Now().Format("2006-01-02 15:04:05"),
		StatDate:   time.Unix(res.MaxTime, 0).Format("2006-01-02"),
		Instance:   instanceId,
		Host:       host,
	}

	// 入库 pg
	if err = pg.InsertData(aliyun); err != nil {
		zap.L().Error("Kafka.InsertData failed", zap.Error(err))
		return
	}

	return
}

func FormatRes(response *cms20190101.DescribeMetricListResponse, maxValue string) (result *AliRespJson, err error) {
	//fmt.Printf("aliyun response.Body is %T", *response.Body.Datapoints)
	//fmt.Println(reflect.TypeOf(*response.Body.Datapoints))
	var res []map[string]interface{}
	err = json.Unmarshal([]byte(*response.Body.Datapoints), &res)
	if err != nil {
		return
	}

	//排序获取最大值
	resFilter := FindMaxValue(res, maxValue) //"Maximum"

	// 构造一个返回实例实例
	result = &AliRespJson{
		Period:  *response.Body.Period,
		MaxNum:  resFilter[maxValue].(float64),
		MaxTime: int64(resFilter["timestamp"].(float64)) / 1000,
	}

	return
}

func FindMaxValue(arr []map[string]interface{}, maxValue string) map[string]interface{} {
	if len(arr) == 2 {
		if arr[0][maxValue].(float64) > arr[1][maxValue].(float64) {
			return arr[0]
		} else {
			return arr[1]
		}
	} else {
		max_temp := FindMaxValue(arr[1:], maxValue)
		if arr[0][maxValue].(float64) > max_temp[maxValue].(float64) {
			return arr[0]
		} else {
			//fmt.Printf("FindMaxValue max_temp %v\n", max_temp)
			return max_temp
		}
	}
}

func CreateClient(accessKeyId *string, accessKeySecret *string) (_result *cms20190101.Client, _err error) {
	config := &openapi.Config{
		// 您的 AccessKey ID
		AccessKeyId: accessKeyId,
		// 您的 AccessKey Secret
		AccessKeySecret: accessKeySecret,
	}
	// 访问的域名
	config.Endpoint = tea.String("metrics.cn-beijing.aliyuncs.com")
	_result = &cms20190101.Client{}
	_result, _err = cms20190101.NewClient(config)

	return _result, _err
}
